package com.yunmai.web.services.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunmai.account.center.sdk.api.UserCenterApi;
import com.yunmai.account.center.sdk.vo.AccountGuestSession;
import com.yunmai.account.center.sdk.vo.AccountSession;
import com.yunmai.account.center.sdk.vo.ConfigInfo;
import com.yunmai.web.common.context.ContextHolder;
import com.yunmai.web.config.config.AppConfig;
import com.yunmai.web.config.config.UserCenterConfig;
import com.yunmai.web.domain.AccountCenterUserEntity;
import com.yunmai.web.domain.AccountDetailEntity;
import com.yunmai.web.domain.PhoneUserEntity;
import com.yunmai.web.exception.BusinessResponseException;
import com.yunmai.web.exception.error.ErrorMessageResponse;
import com.yunmai.web.repositories.IPhoneUserMapper;
import com.yunmai.web.services.IAccountCenterUserService;
import com.yunmai.web.services.IAccountDetailService;
import com.yunmai.web.services.IPhoneUserService;
import com.yunmai.web.vo.AccountLoginVO;
import com.yunmai.web.vo.AccountSessionInfo;
import com.yunmai.web.vo.AccountVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author WangChen
 * @since 2021-03-17
 */
@Service
public class PhoneUserServiceImpl extends ServiceImpl<IPhoneUserMapper, PhoneUserEntity> implements IPhoneUserService {

    @Autowired
    private IPhoneUserService phoneUserService;

    @Autowired
    private IAccountCenterUserService accountCenterUserService;

    @Autowired
    private IAccountDetailService accountDetailService;

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private UserCenterConfig userCenterConfig;

    @PostConstruct
    public void initConfig() {
        UserCenterApi.setOptions(new ConfigInfo(appConfig.getAppId(), appConfig.getSecret(), userCenterConfig.getEnvironment()));
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public AccountSessionInfo register(AccountVO accountVO) {

        LambdaQueryWrapper<PhoneUserEntity> wrapper = Wrappers.lambdaQuery(PhoneUserEntity.class)
                .eq(PhoneUserEntity::getPhone, accountVO.getPhone());

        if (ObjectUtils.isNotEmpty(phoneUserService.getOne(wrapper))) {
            throw new BusinessResponseException(ErrorMessageResponse.ACCOUNT_ALREADY_EXIST.convert());
        }

        String authId = RandomUtil.randomString(6);
        String password = RandomUtil.randomString(6);

        AccountSession accountSession = UserCenterApi.user().registerAccount(authId, password, accountVO.getClientId());

        AccountCenterUserEntity accountCenterUserEntity = accountCenterUserService.save(authId, password);

        PhoneUserEntity phoneUserEntity = new PhoneUserEntity();
        phoneUserEntity.setAccountCenterUserId(accountCenterUserEntity.getGuid());
        phoneUserEntity.setPhone(accountVO.getPhone());
        phoneUserEntity.setPassword(SecureUtil.md5(accountVO.getPassword()));

        phoneUserService.save(phoneUserEntity);

        AccountDetailEntity accountDetailEntity = accountDetailService.create(accountVO.getPhone(), accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());

        return accountSessionInfo;
    }

    @Override
    public AccountSessionInfo registerGuest() {

        String authId = RandomUtil.randomString(8);

        AccountSession accountSession = UserCenterApi.user().registerGuest(authId);

        AccountDetailEntity accountDetailEntity = accountDetailService.create(authId, accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());
        accountSessionInfo.setClientId(authId);

        return accountSessionInfo;
    }


    @Override
    public AccountSessionInfo loginGuest(String clientId) {

        AccountGuestSession accountSession = UserCenterApi.user().loginGuest(clientId);

        AccountDetailEntity accountDetailEntity = accountDetailService.find(accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());

        return accountSessionInfo;
    }

    @Override
    public AccountSessionInfo login(AccountLoginVO accountLoginVO) {

        AccountCenterUserEntity accountCenterUserEntity = accountCenterUserService.find(
                phoneUserService.find(accountLoginVO.getPhone(), accountLoginVO.getPassword()).getAccountCenterUserId());

        AccountSession accountSession = UserCenterApi.user().loginAccount(accountCenterUserEntity.getAuthId(), accountCenterUserEntity.getPassword());

        AccountDetailEntity accountDetailEntity = accountDetailService.find(accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());

        return accountSessionInfo;
    }


    @Override
    public AccountSessionInfo login(String phone) {

        AccountCenterUserEntity accountCenterUserEntity = accountCenterUserService.find(
                phoneUserService.find(phone).getAccountCenterUserId());

        AccountSession accountSession = UserCenterApi.user().loginAccount(accountCenterUserEntity.getAuthId(), accountCenterUserEntity.getPassword());

        AccountDetailEntity accountDetailEntity = accountDetailService.find(accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());

        return accountSessionInfo;
    }


    @Override
    public PhoneUserEntity find(String phone, String password) {
        LambdaQueryWrapper<PhoneUserEntity> wrapper = Wrappers.lambdaQuery(PhoneUserEntity.class)
                .eq(PhoneUserEntity::getPhone, phone);
        PhoneUserEntity phoneUserEntity = phoneUserService.getOne(wrapper);
        if (ObjectUtils.isEmpty(phoneUserEntity)) {
            throw new BusinessResponseException(ErrorMessageResponse.ACCOUNT_NOT_EXIST.convert());
        }
        if (!StrUtil.equals(SecureUtil.md5(password), phoneUserEntity.getPassword())) {
            throw new BusinessResponseException(ErrorMessageResponse.ACCOUNT_PWD_NOT_RIGHT.convert());
        }
        return phoneUserEntity;
    }

    @Override
    public PhoneUserEntity find(String phone) {
        LambdaQueryWrapper<PhoneUserEntity> wrapper = Wrappers.lambdaQuery(PhoneUserEntity.class)
                .eq(PhoneUserEntity::getPhone, phone);
        PhoneUserEntity phoneUserEntity = phoneUserService.getOne(wrapper);
        if (ObjectUtils.isEmpty(phoneUserEntity)) {
            throw new BusinessResponseException(ErrorMessageResponse.ACCOUNT_NOT_EXIST.convert());
        }
        return phoneUserEntity;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public AccountSessionInfo changePassword(String phone, String password) {

        LambdaQueryWrapper<PhoneUserEntity> wrapper = Wrappers.lambdaQuery(PhoneUserEntity.class)
                .eq(PhoneUserEntity::getPhone, phone);
        PhoneUserEntity phoneUserEntity = phoneUserService.getOne(wrapper);
        if (ObjectUtils.isEmpty(phoneUserEntity)) {
            throw new BusinessResponseException(ErrorMessageResponse.ACCOUNT_NOT_EXIST.convert());
        }
        phoneUserEntity.setPassword(SecureUtil.md5(password));
        phoneUserService.updateById(phoneUserEntity);

        AccountCenterUserEntity accountCenterUserEntity = accountCenterUserService.find(phoneUserEntity.getAccountCenterUserId());

        AccountSession accountSession = UserCenterApi.user().loginAccount(accountCenterUserEntity.getAuthId(), accountCenterUserEntity.getPassword());

        AccountDetailEntity accountDetailEntity = accountDetailService.find(accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());

        return accountSessionInfo;
    }

    @Override
    public AccountSessionInfo getSession() {

        AccountGuestSession accountSession = ContextHolder.getSession();

        AccountDetailEntity accountDetailEntity = accountDetailService.find(accountSession.getAccountId());

        AccountSessionInfo accountSessionInfo = new AccountSessionInfo();
        accountSessionInfo.setGuid(accountSession.getAccountId());
        accountSessionInfo.setAvatar(accountDetailEntity.getAvatar());
        accountSessionInfo.setName(accountDetailEntity.getName());
        accountSessionInfo.setToken(accountSession.getToken());
        accountSessionInfo.setPowers(accountSession.getPowers());
        accountSessionInfo.setClientId(accountSession.getClientId());

        return accountSessionInfo;
    }
}
